﻿using java.io;
using java.lang;
using java.security;
using javax.crypto;
using javax.crypto.spec;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        /** 密钥长度: 128, 192 or 256 */
        private static int KEY_SIZE = 128;

        /** 加密/解密算法名称 */
        private static string ALGORITHM = "AES";

        /** 随机数生成器（RNG）算法名称 */
        private static string RNG_ALGORITHM = "SHA1PRNG";

        static void Main(string[] args)
        {
            System.Console.WriteLine("Java AES加密、解密!");
            System.Console.WriteLine("待加密内容：testAppId");
            string decryptString = encrypt("testAppId", "testAppId");
            System.Console.WriteLine(decryptString);
            string strDecrypt = decrypt(decryptString, "testAppId");
            System.Console.WriteLine(strDecrypt);
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="encryptString">待加密内容</param>
        /// <param name="passWord">解密密钥</param>
        /// <returns></returns>
        public static string encrypt(string encryptString, string passWord)
        {
            string result = null;
            try
            {
                // 生成Key
                KeyGenerator keyGenerator;
                keyGenerator = KeyGenerator.getInstance("AES");
                // 使用这种初始化方法可以特定种子来生成密钥，这样加密后的密文是唯一固定的。
                //keyGenerator.init(128, new SecureRandom(passWord.getBytes()));
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(Encoding.UTF8.GetBytes(passWord));
                keyGenerator.init(128, secureRandom);
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] keyBytes = secretKey.getEncoded();
                // Key转换
                Key key = new SecretKeySpec(keyBytes, "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, key);
                byte[] encodeResult = cipher.doFinal(Encoding.UTF8.GetBytes(encryptString));
                result = parseByte2HexStr(encodeResult);
            }
            catch (InvalidKeyException e)
            {
                e.printStackTrace();
            }
            catch (IllegalBlockSizeException e)
            {
                e.printStackTrace();
            }
            catch (BadPaddingException e)
            {
                e.printStackTrace();
            }
            catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            }
            catch (NoSuchPaddingException e)
            {
                e.printStackTrace();
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
            return result;
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="decryptString">待解密内容</param>
        /// <param name="passWord">解密密钥</param>
        /// <returns></returns>
        public static string decrypt(string decryptString, string passWord)
        {
            string result = null;
            try
            {
                byte[] decryptBytes = parseHexStr2Byte(decryptString);
                // 生成Key
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                // 使用这种初始化方法可以特定种子来生成密钥，这样加密后的密文是唯一固定的。
                //keyGenerator.init(128, new SecureRandom(passWord.getBytes()));
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(Encoding.UTF8.GetBytes(passWord));
                keyGenerator.init(128, secureRandom);
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] keyBytes = secretKey.getEncoded();
                // Key转换
                Key key = new SecretKeySpec(keyBytes, "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, key);
                byte[] decodeResult = cipher.doFinal(decryptBytes);
                result = Encoding.UTF8.GetString(decodeResult);
            }
            catch (NumberFormatException e)
            {
                e.printStackTrace();
                return "AES解密参数非法！";
            }
            catch (InvalidKeyException e)
            {
                e.printStackTrace();
            }
            catch (IllegalBlockSizeException e)
            {
                e.printStackTrace();
            }
            catch (BadPaddingException e)
            {
                e.printStackTrace();
            }
            catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            }
            catch (NoSuchPaddingException e)
            {
                e.printStackTrace();
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }

            return result;
        }

        /// <summary>
        /// 数据解密: 密文 -> 明文
        /// </summary>
        /// <param name="cipherBytes"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static byte[] decrypt(byte[] cipherBytes, byte[] key)
        {
            // 生成密钥对象
            SecretKey secKey = generateKey(key);

            // 获取 AES 密码器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            // 初始化密码器（解密模型）
            cipher.init(Cipher.DECRYPT_MODE, secKey);

            // 解密数据, 返回明文
            byte[] plainBytes = cipher.doFinal(cipherBytes);

            return plainBytes;
        }

        /// <summary>
        /// 生成密钥对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private static SecretKey generateKey(byte[] key)
        {
            // 创建安全随机数生成器
            SecureRandom random = SecureRandom.getInstance(RNG_ALGORITHM);
            // 设置 密钥key的字节数组 作为安全随机数生成器的种子
            random.setSeed(key);

            // 创建 AES算法生成器
            KeyGenerator gen = KeyGenerator.getInstance(ALGORITHM);
            // 初始化算法生成器
            gen.init(KEY_SIZE, random);

            // 生成 AES密钥对象, 也可以直接创建密钥对象: return new SecretKeySpec(key, ALGORITHM);
            return gen.generateKey();
        }

        /// <summary>
        /// 将二进制转换成16进制 
        /// </summary>
        /// <param name="buf"></param>
        /// <returns></returns>
        public static string parseByte2HexStr(byte[] buf)
        {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < buf.Length; i++)
            {
                string hex = Integer.toHexString(buf[i] & 0xFF);
                if (hex.Length == 1)
                {
                    hex = '0' + hex;
                }
                sb.append(hex.ToUpper());
            }
            return sb.toString();
        }

        /// <summary>
        /// 将16进制转换为二进制
        /// </summary>
        /// <param name="hexStr"></param>
        /// <returns></returns>
        public static byte[] parseHexStr2Byte(string hexStr)
        {
            string strResult = string.Empty;
            foreach (char c in hexStr)
            {
                int v = Convert.ToInt32(c.ToString(), 16);
                int v2 = int.Parse(Convert.ToString(v, 2));
                // 去掉格式串中的空格，即可去掉每个4位二进制数之间的空格，
                strResult += string.Format("{0:d4} ", v2);
            }
            strResult = strResult.Replace(" ", "");
            //二进制字符串转化为byte[]
            byte[] returnBytes = new byte[strResult.Length / 8];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(strResult.Substring(i * 8, 8), 2);
            }
            return returnBytes;
        }
    }
}
